home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Online / hsc / source / hsclib / defattr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-02  |  15.7 KB  |  655 lines

  1. /*
  2.  * This source code is part of hsc, a html-preprocessor,
  3.  * Copyright (C) 1995-1997  Thomas Aglassinger
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20. /*
  21.  * hsclib/defattr.c
  22.  *
  23.  * functions to define new attribute
  24.  * and manipulate attribute lists
  25.  *
  26.  * updated: 31-May-1997
  27.  * created:  6-Jan-1995
  28.  */
  29.  
  30. #define NOEXTERN_HSCLIB_DEFATTR
  31.  
  32. #include "hsclib/inc_base.h"
  33.  
  34. #include "hsclib/defattr.h"
  35. #include "hsclib/eval.h"
  36. #include "hsclib/input.h"
  37.  
  38. /*
  39.  *-------------------------------------
  40.  * misc. functions
  41.  *-------------------------------------
  42.  */
  43. static BYTE str2vartype(STRPTR s)
  44. {
  45.     BYTE vartype = VT_NONE;
  46.  
  47.     if (!upstrcmp(VT_STR_URI, s))
  48.         vartype = VT_URI;
  49.     else if (!upstrcmp(VT_STR_STRING, s))
  50.         vartype = VT_STRING;
  51.     else if (!upstrcmp(VT_STR_BOOL, s))
  52.         vartype = VT_BOOL;
  53.     else if (!upstrcmp(VT_STR_NUM, s))
  54.         vartype = VT_NUM;
  55.     else if (!upstrcmp(VT_STR_ENUM, s))
  56.         vartype = VT_ENUM;
  57.     else if (!upstrcmp(VT_STR_ID, s))
  58.         vartype = VT_ID;
  59.     else if (!upstrcmp(VT_STR_COLOR, s))
  60.         vartype = VT_COLOR;
  61.  
  62.     return (vartype);
  63. }
  64.  
  65. /*
  66.  * check_varlist: check for required attributes missing
  67.  *
  68.  * result: TRUE, if all attributes ok
  69.  */
  70. static BOOL check_reqvar(HSCPRC * hp, HSCATTR * var)
  71. {
  72.     BOOL ok = TRUE;
  73.  
  74.     if ((var->varflag & VF_REQUIRED)
  75.         && (!var->text))
  76.     {
  77.         hsc_message(hp, MSG_MISS_REQ_ATTR,
  78.                     "required %A missing", var);
  79.         ok = FALSE;
  80.     }
  81.  
  82.     return (ok);
  83. }
  84.  
  85. BOOL check_varlist(HSCPRC * hp, DLLIST * varlist)
  86. {
  87.     DLNODE *nd = varlist->first;
  88.     BOOL ok = TRUE;
  89.  
  90.     while (nd)
  91.     {
  92.         ok &= check_reqvar(hp, (HSCATTR *) (nd->data));
  93.         nd = nd->next;
  94.     }
  95.  
  96.     return (ok);
  97. }
  98.  
  99. /*
  100.  *-------------------------------------
  101.  * scope functions
  102.  *-------------------------------------
  103.  */
  104.  
  105. /*
  106.  * get_mci
  107.  *
  108.  */
  109. LONG get_mci(HSCPRC * hp)
  110. {
  111.     hp->tag_call_id++;
  112.  
  113.     return (hp->tag_call_id);
  114. }
  115.  
  116. /*
  117.  * unget_mci
  118.  *
  119.  */
  120. VOID unget_mci(HSCPRC * hp)
  121. {
  122.     hp->tag_call_id--;
  123.     if (hp->tag_call_id < 0)
  124.     {
  125.         panic("MCI underflow");
  126.     }
  127. }
  128.  
  129. /*
  130.  * get_current_mci
  131.  *
  132.  */
  133. LONG get_current_mci(HSCPRC * hp)
  134. {
  135.     return (hp->tag_call_id);
  136. }
  137.  
  138. /*
  139.  *-------------------------------------
  140.  * define a new var from input file
  141.  *-------------------------------------
  142.  */
  143.  
  144. /*
  145.  * read_enum_str
  146.  *
  147.  * sidefx: modifies tmpstr
  148.  */
  149. static BOOL read_enum_str(HSCPRC * hp, HSCATTR * var)
  150. {
  151.     HSCATTR *attr = new_hscattr(PREFIX_TMPATTR "enumerator");
  152.     attr->vartype = VT_STRING;
  153.  
  154.     /* store enumstr in var-struct */
  155.     if (eval_expression(hp, attr, NULL))
  156.     {
  157.         DDA(fprintf(stderr, DHL "  enum: %s\n", estr2str(hp->tmpstr)));
  158.         var->enumstr = strclone(get_vartext(attr));
  159.     }
  160.  
  161.     del_hscattr(attr);
  162.  
  163.     return ((BOOL) (!hp->fatal));
  164. }
  165.  
  166. /*
  167.  * check_attr_option
  168.  *
  169.  * check if a attribute-option-string is equal to an id/short id.
  170.  * if so, set the corresponding option value within the attribute.
  171.  *
  172.  * params: option..option string to check for (read from input)
  173.  *         attr....attribute to update option value for
  174.  *         id......id string of option (eg "REQUIRED")
  175.  *         sid.....short id string (eg "R")
  176.  *         value...option value to OR with old tag's option value
  177.  * result: TRUE, if tag's option value updated
  178.  */
  179. static BOOL check_attr_option(HSCPRC * hp, STRPTR option, HSCATTR * attr, STRPTR id, STRPTR sid, ULONG value, ULONG unmasked_flags)
  180. {
  181.     BOOL found = FALSE;
  182.  
  183.     if (!((upstrcmp(option, id)) && (upstrcmp(option, sid))))
  184.     {
  185.         DDA(fprintf(stderr, DHL "  option %s\n", id));
  186.  
  187.         if (value & unmasked_flags)
  188.         {
  189.             hsc_message(hp, MSG_ILLG_ATTR_FLAG,
  190.                         "attribute option %q not allowed in this context",
  191.                         id);
  192.         }
  193.         else
  194.             attr->varflag |= value;
  195.  
  196.         found = TRUE;
  197.     }
  198.  
  199.     return (found);
  200. }
  201.  
  202. /*
  203.  * define_var
  204.  *
  205.  * define a new var with reading its def from input file
  206.  * (starts parsing after ":", so ":" has to be read before)
  207.  *
  208.  * params: varname..name of new var
  209.  *         varlist..list new var should be inserted at the beginning
  210.  *         inpf.....input file where to read def from
  211.  *         flag.....flags: VF_ONLYONCE to avoid re-definition of a var
  212.  * result: ptr to new var
  213.  *
  214.  * definition syntax in input file:
  215.  *   <vartype>[/flag]["="<deftext value>]
  216.  *   legal vartypes: see VT_STR_xx in "vars.h"
  217.  *   legal flags   : see VF_STR_xx in "vars.h"
  218.  */
  219. HSCATTR *define_var(HSCPRC * hp, DLLIST * varlist, ULONG unmasked_flags)
  220. {
  221.     HSCATTR *var = NULL;        /* result */
  222.     BOOL ok = FALSE;
  223.     BYTE val_vartype = VT_NONE; /* var-type (numeric) */
  224.     BOOL newattr = FALSE;       /* next word read from input */
  225.     STRPTR nw = NULL;
  226.     STRPTR varname = NULL;
  227.     BOOL eof_called = FALSE;    /* used at end-of-func, if nw==NULL */
  228.     INFILE *inpf = hp->inpf;
  229.  
  230.     /* read attribute name */
  231.     nw = infget_attrid(hp);
  232.     if (nw)
  233.     {
  234.         varname = strclone(nw); /* remember attribute name */
  235.     }
  236.     else
  237.         eof_called = TRUE;      /* err_eof() called already */
  238.  
  239.     /* read attribute type */
  240.     if (nw)
  241.         if (parse_wd(hp, ":"))
  242.         {
  243.             nw = infgetw(inpf);
  244.             if (nw)
  245.                 val_vartype = str2vartype(nw);
  246.         }
  247.         else
  248.             inungetcw(inpf);
  249.  
  250.     if (nw)
  251.     {
  252.         /*
  253.          * look if attr already exist;
  254.          * if yes, clear old attribute
  255.          * to redefine the new one
  256.          */
  257.         var = find_varname(varlist, varname);
  258.         if (var)
  259.         {
  260.             DLNODE *nd = find_attrnode(varlist, varname);
  261.  
  262.             /* remove old attribute */
  263.             if (nd)
  264.                 del_dlnode(varlist, nd);
  265.             else
  266.                 panic("no node for redefined attribute");
  267.  
  268.             hsc_message(hp, MSG_ATTR_REDEFINED,
  269.                         "redefined %a", varname);
  270.         }
  271.  
  272.         /*
  273.          * create new attribute
  274.          */
  275.         DDA(fprintf(stderr, DHL "new attr: %s\n", varname));
  276.         var = app_var(varlist, varname);
  277.  
  278.         /* set type */
  279.         var->vartype = val_vartype;
  280.         if (var->vartype == VT_ENUM)
  281.         {
  282.             /* init enum-attribute */
  283.             read_enum_str(hp, var);
  284.         }
  285.         else if (var->vartype == VT_BOOL)
  286.         {
  287.             /* init boolean attr with FALSE */
  288.             set_varbool(var, FALSE);
  289.         }
  290.  
  291.         newattr = TRUE;
  292.  
  293.     }
  294.  
  295.     /* disable "/STRIPEXT" and "/GETSIZE" for non-URI-attributes */
  296.     if (nw)
  297.     {
  298.         if (var->vartype != VT_URI)
  299.             unmasked_flags |= VF_GETSIZE | VF_STRIPEXT;
  300.  
  301.         nw = infgetw(inpf);     /* get net word */
  302.     }
  303.  
  304.     /*
  305.      * handle attribute flags
  306.      */
  307.     while (nw && !strcmp(nw, "/"))
  308.     {
  309.         nw = infgetw(inpf);     /* read flag identifier */
  310.         if (nw)
  311.         {
  312.             BOOL ok = FALSE;
  313.  
  314.             ok |= check_attr_option(hp, nw, var,
  315.                                     VF_CONST_STR, VF_CONST_SHT,
  316.                                     VF_CONST, unmasked_flags);
  317.             ok |= check_attr_option(hp, nw, var,
  318.                                     VF_GLOBAL_STR, VF_GLOBAL_SHT,
  319.                                     VF_GLOBAL, unmasked_flags);
  320.             ok |= check_attr_option(hp, nw, var,
  321.                                     VF_JERK_STR, VF_JERK_SHT,
  322.                                     VF_JERK, unmasked_flags);
  323.             ok |= check_attr_option(hp, nw, var,
  324.                                     VF_ONLYONCE_STR, VF_ONLYONCE_SHT,
  325.                                     VF_ONLYONCE, unmasked_flags);
  326.             ok |= check_attr_option(hp, nw, var,
  327.                                     VF_REQUIRED_STR, VF_REQUIRED_SHT,
  328.                                     VF_REQUIRED, unmasked_flags);
  329.             ok |= check_attr_option(hp, nw, var,
  330.                                     VF_GETSIZE_STR, VF_GETSIZE_SHT,
  331.                                     VF_GETSIZE, unmasked_flags);
  332.             ok |= check_attr_option(hp, nw, var,
  333.                                     VF_STRIPEXT_STR, VF_STRIPEXT_SHT,
  334.                                     VF_STRIPEXT, unmasked_flags);
  335.             if (!ok)
  336.             {
  337.                 hsc_message(hp, MSG_UNKN_ATTR_OPTION,
  338.                             "unknown attribute flag %q", nw);
  339.             }
  340.  
  341.             /* read next word (should be "/", "=" or next attr / ">") */
  342.             nw = infgetw(inpf);
  343.         }
  344.         else
  345.             hsc_msg_eof(hp, "defining attribute");
  346.  
  347.     }
  348.  
  349.     /*
  350.      * handle default value
  351.      */
  352.     if (nw && !strcmp(nw, "="))
  353.     {
  354.         /* get new deftext value */
  355.         STRPTR new_deftext = NULL;
  356.         LONG old_attrflag = var->varflag;
  357.  
  358.         /* disable quotemode-checking */
  359.         var->varflag |= VF_KEEP_QUOTES;
  360.  
  361.         if (!(var->deftext))
  362.             new_deftext = eval_expression(hp, var, NULL);
  363.         else
  364.         {
  365.             STRPTR dummy;
  366.  
  367.             hsc_message(hp, MSG_SYMB_2ND_DEFAULT,
  368.                         "default value for %A already set", var);
  369.  
  370.             /* skip illegal default value */
  371.             dummy = eval_expression(hp, var, NULL);
  372.         }
  373.  
  374.         /* restore quotemode-checking */
  375.         var->varflag = old_attrflag;
  376.  
  377.         /* store default text value */
  378.         if (new_deftext)
  379.             var->deftext = strclone(new_deftext);
  380.  
  381.         /* read next word, only to be ungotten below */
  382.         nw = infgetw(inpf);
  383.     }
  384.  
  385.     /* check for unexpected end of file */
  386.     if (!nw)
  387.     {
  388.         if (!eof_called)
  389.             hsc_msg_eof(hp, "defining attribute");
  390.     }
  391.     else
  392.     {
  393.         /* end of var definition reached */
  394.         inungetcw(inpf);
  395.         ok = TRUE;
  396.     }
  397.  
  398.     /* cleanup */
  399.     if (!ok && var)
  400.     {
  401.         DLNODE *nd = find_attrnode(varlist, varname);
  402.         if (nd)
  403.             del_dlnode(varlist, (APTR) nd);
  404.         else
  405.             del_hscattr(var);
  406.         var = NULL;
  407.     }
  408.     ufreestr(varname);
  409.  
  410.     return (var);
  411. }
  412.  
  413. /*
  414.  * define_attr_by_hp
  415.  *
  416.  * define a new attribute with obtaining data from hsc-process
  417.  *
  418.  * SEE ALSO:
  419.  *   define_attr_by_text
  420.  */
  421. HSCATTR *define_attr_by_hp(HSCPRC * hp, STRPTR default_value, ULONG unmasked_flags)
  422. {
  423.     HSCATTR *attr = define_var(hp, hp->defattr, 0);
  424.     if (attr)
  425.     {
  426.         /* set scope for local attribute */
  427.         if (attr->varflag & VF_GLOBAL)
  428.         {
  429.             attr->macro_id = MCI_GLOBAL;
  430.         }
  431.         else
  432.         {
  433.             attr->macro_id = get_current_mci(hp);
  434.         }
  435.  
  436.         /* see "attrib.h" why this */
  437.         attr->varflag |= VF_MACRO;
  438.  
  439.         /* set new value (copy from default) if passed */
  440.         if (get_vardeftext(attr))
  441.         {
  442.             if (default_value)
  443.             {
  444.                 panic("default value already set");
  445.             }
  446.             else
  447.             {
  448.                 clr_vartext(attr);
  449.             }
  450.         }
  451.  
  452.         /* set default value passed in function args */
  453.         if (default_value)
  454.         {
  455.             set_vartext(attr, default_value);
  456.         }
  457.  
  458.         /* remove default value */
  459.         clr_attrdef(attr);
  460.     }
  461.  
  462.     return (attr);
  463. }
  464.  
  465. /*
  466.  * define_attr_by_text
  467.  *
  468.  * define a new attribute with attribute definition passed as
  469.  * string. The new attribute is assigned to the global attr-list
  470.  * (by default, with a local scope)
  471.  *
  472.  * params: varname..name of new var
  473.  *         flag.....flags: VF_ONLYONCE to avoid re-definition of a var
  474.  * result: ptr to new var
  475.  *
  476.  * NOTE:
  477.  *   The new attribute will be declared as if a corresponding
  478.  *   <$define> showed up in the source. It will be assigned to
  479.  *   the local scope; you will need to add a "/GLOBAL" to the
  480.  *   description text if you want to avoid this
  481.  *
  482.  *   It's recommended not to setup a default value, if you are
  483.  *   not sure that it can't contain data that will cause error
  484.  *   messages to show up (like value=xy"zw'bl)
  485.  *
  486.  * definition syntax in input file:
  487.  *   <varname>":"<vartype>[/flag]["="<deftext value>]
  488.  *
  489.  * EXAMPLE:
  490.  *   define_attr_by_text(hp,"sepp:string/global='sepp'", 0)
  491.  *
  492.  * SEE ALSO:
  493.  *   define_var()
  494.  */
  495. HSCATTR *define_attr_by_text(HSCPRC * hp, STRPTR attr_text, STRPTR default_value, ULONG unmasked_flags)
  496. {
  497.     /* NOTE: this functions works a bit strange */
  498.     EXPSTR *define_text = init_estr(0);
  499.     INFILE *old_inpf = hp->inpf;
  500.     HSCATTR *attr = NULL;
  501.  
  502.     /* create attribute definition */
  503.     set_estr(define_text, attr_text);
  504.     app_estr(define_text, ">");
  505.  
  506.     hp->inpf = infopen_str(PARENT_FILE_ID "define_attr_by_text",
  507.                            estr2str(define_text), 0);
  508.  
  509.     /* process attribute definition */
  510.     if (hp->inpf)
  511.     {
  512.         attr = define_attr_by_hp(hp, default_value, unmasked_flags);
  513.         infclose(hp->inpf);
  514.     }
  515.  
  516.     /* cleanup */
  517.     hp->inpf = old_inpf;
  518.     del_estr(define_text);
  519.  
  520.     return (attr);
  521. }
  522.  
  523. /*
  524.  *-------------------------------------
  525.  * copy & remove local vars to/from
  526.  * global varlist
  527.  *-------------------------------------
  528.  */
  529.  
  530. /*
  531.  * copy_local_var
  532.  *
  533.  * copies a local attribute to the global attribute list
  534.  *
  535.  * NOTE: the VF_MACRO-flag of the copy is disabled!
  536.  */
  537. static HSCATTR *copy_local_var(DLLIST * destlist, HSCATTR * locvar, ULONG mci)
  538. {
  539.     HSCATTR *var = app_var(destlist, locvar->name);
  540.  
  541.     var->macro_id = mci;
  542.     var->vartype = locvar->vartype;
  543.     var->varflag = locvar->varflag & (~VF_MACRO);       /* disable VF_MACRO */
  544.     set_vartext(var, locvar->text);
  545.     var->quote = locvar->quote;
  546.  
  547.     return (var);
  548. }
  549.  
  550. /*
  551.  * copy_local_vars
  552.  *
  553.  * add all local attributes of a macro to the global
  554.  * attribute list.
  555.  *
  556.  */
  557. BOOL copy_local_varlist(DLLIST * destlist, DLLIST * varlist, ULONG mci)
  558. {
  559.     BOOL ok = TRUE;
  560.  
  561.     if (mci == MCI_ERROR)
  562.     {
  563.         panic("mci=MCI_ERROR");
  564.     }
  565.     else
  566.     {
  567.         DLNODE *nd = varlist->first;
  568.         HSCATTR *var;
  569.  
  570.         while (nd && ok)
  571.         {
  572.             var = copy_local_var(destlist, (HSCATTR *) (nd->data), mci);
  573.             ok &= (BOOL) (var != NULL);
  574.             nd = nd->next;
  575.         }
  576.     }
  577.  
  578.     return (ok);
  579. }
  580.  
  581. /*
  582.  * set_local_var
  583.  *
  584.  * copies a local attribute to the global attribute list
  585.  *
  586.  * NOTE: the VF_MACRO-flag of the set is enabled!
  587.  */
  588. static HSCATTR *set_local_var(DLLIST * destlist, HSCATTR * locvar, ULONG mci)
  589. {
  590.     HSCATTR *var = find_varname(destlist, locvar->name);
  591.  
  592.     if (var)
  593.     {
  594.         var->macro_id = mci;
  595.         var->vartype = locvar->vartype;
  596.         set_vartext(var, locvar->text);
  597.     }
  598.     else
  599.     {
  600.         panic("set_local_var to UNKNOWN ATTR");
  601.     }
  602.  
  603.     return (var);
  604. }
  605.  
  606. /*
  607.  * set_local_vars
  608.  *
  609.  * add all local attributes of a macro to the global
  610.  * attribute list.
  611.  *
  612.  */
  613. BOOL set_local_varlist(DLLIST * destlist, DLLIST * varlist, ULONG mci)
  614. {
  615.     BOOL ok = TRUE;
  616.  
  617.     if (mci == MCI_ERROR)
  618.     {
  619.         panic("mci=MCI_ERROR");
  620.     }
  621.     else
  622.     {
  623.         DLNODE *nd = varlist->first;
  624.         HSCATTR *var;
  625.  
  626.         while (nd && ok)
  627.         {
  628.             var = set_local_var(destlist, (HSCATTR *) (nd->data), mci);
  629.             ok &= (BOOL) (var != NULL);
  630.             nd = nd->next;
  631.         }
  632.     }
  633.  
  634.     return (ok);
  635. }
  636.  
  637. /*
  638.  * remove_local_varlist
  639.  */
  640. VOID remove_local_varlist(DLLIST * varlist, ULONG mci)
  641. {
  642.     DLNODE *nd = varlist->first;
  643.  
  644.     while (nd)
  645.     {
  646.         HSCATTR *var = (HSCATTR *) nd->data;    /* var data of node */
  647.         DLNODE *nd_nxt = nd->next;      /* next node */
  648.  
  649.         if (var->macro_id == mci)
  650.             del_dlnode(varlist, nd);
  651.  
  652.         nd = nd_nxt;
  653.     }
  654. }
  655.